﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Code.Commen;
using System.Security.Cryptography;
using Code.Models;

namespace Code.BLL
{
    public class UserManage : ManageBase<Users>
    {

        /// <summary>
        /// 用户登陆
        /// </summary>
        /// <param name="loginName">登录名</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        public LoginResult UserLogin(string loginName, string password, string loginIP, out Guid? uid)
        {
            LoginResult lr;
            if (string.IsNullOrEmpty(loginName))
            {
                throw new ArgumentNullException("loginName", "用户名不能为空");
            }
            if (string.IsNullOrEmpty(password))
            {
                throw new ArgumentNullException("password", "密码不能为空");
            }
            uid = null;
            var user = base.Select(s => s.Where(p => p.LoginName == loginName).Select(p => new {p.ID,p.Password,p.Salt,p.State }).FirstOrDefault());
            MD5 md5 = MD5.Create();
            if (user == null)
                return LoginResult.UnExist;
            if(user.State!=(short)UserState.Normal&&user.State!=(short)UserState.Freez)
            {
                var lg = new
                {
                     UserID=user.ID,
                     LoginIP=loginIP,
                     LoginResult=LoginResult.Locked,
                     FailCause = ((UserState)user.State).GetName()
                };
                base.Insert<LoginLog>(lg);
                throw new AppException("您已经被"+((UserState)user.State).GetName());
            }
            else if (user.Password.Equals(md5.ComputeHash(password, user.Salt)))
            {
                uid = user.ID;
                lr = LoginResult.Normal;
            }
            else
            {
                lr = LoginResult.PWDError;
            }
            var loginLog = new
            {
                 UserID=user.ID,
                 LoginIP=loginIP,
                 LoginResult=(short)lr,
                 FailCause=lr.GetName()
            };
            base.Insert<LoginLog>(loginLog);
            return lr;
        }

        /// <summary>
        /// 添加用户
        /// 请确保新增用户时已经设置该用户的奖金
        /// </summary>
        /// <param name="commandID">新用户上级ID</param>
        /// <param name="loginName">新用户登录名</param>
        /// <param name="password">新用户登录密码</param>
        /// <param name="type"></param>
        /// <param name="AllChildCount"></param>
        /// <param name="AllSurrogateCount"></param>
        /// <param name="NextMemberCount"></param>
        /// <param name="NextSurrogateCount"></param>
        /// <param name="setWin"></param>
        /// <param name="manage"></param>
        /// <param name="uid"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public int AddUser(Guid? commandID, string loginName, string password, UserType type,bool enableAddChildConfig,int AllChildCount, bool setWin, bool manage, out Guid? uid, out string msg)
        {
            int rs = -1;
            msg = "";
            var commands="";
            UserAddChildConfig uacc = null;
            if (commandID.HasValue)
            {
                #region 判断配额
                var accm = new AddChildConfigManage();
                uacc = accm.GetNowAddChildConfig(commandID.Value);
                if (uacc.State == (short)AddChildConfigState.Locked)
                {
                    msg = "您的添加下级功能已被锁定，请和上级或管理员联系!";
                    uid = null;
                    return -3;
                }
                else if (enableAddChildConfig&&uacc.AllChildCount <= 0)
                {
                    msg = "您的可添加下级名额已用完，您目前不能添加下级!";
                    uid = null;
                    return -3;
                }
                else if (enableAddChildConfig&&type == UserType.Surrogate && AllChildCount < 0)
                {
                    msg = "您为下级设置的配额不正确!";
                    uid = null;
                    return -3;
                }
                else if (enableAddChildConfig&&type == UserType.Surrogate && (AllChildCount >= uacc.AllChildCount))
                {
                    msg = "您当前的配额不足，请重新设置!";
                    uid = null;
                    return -4;
                }
                #endregion

                #region 判断当前用户并获取commands
                var command = base.Select(s => s.Where(p => p.ID == commandID.Value).Select(p => new { p.UserType, p.Commands, p.ID, p.CommandID }).FirstOrDefault());
                if (command == null)
                {
                    uid = null;
                    msg = "";
                    return -3;
                }
                else if (command.UserType != (short)UserType.Surrogate)
                {
                    uid = null;
                    msg = "你不是代理，你不能添加会员！";
                    return -1;
                }
                commands = command.CommandID == null ? "" + command.ID : command.Commands + "&" + command.ID;
                #endregion
            }
            var flag = base.Select(s => s.Select(p => p.LoginName).Contains(loginName));
            if (flag)
            {
                uid = null;
                msg = "已存在相同的用户名";
                return -2;
            }
            var salt = Guid.NewGuid().ToString();
            uid = Guid.NewGuid();
            MD5 md5 = MD5.Create();
            if (string.IsNullOrEmpty(password))
            {
                throw new ArgumentNullException("password");
            }
            password = md5.ComputeHash(password, salt);
            #region 增加User表记录
            var u = new NameValue<string,object>
            {
                {"ID", uid},
                {"LoginName",loginName},
                {"Password",password},
                {"Type",(short)type},
                {"salt",salt},
                {"Commands",commands},
                {"CommandID",commandID}
            };
            base.BeginTransaction();
            base.Insert(u);
            #endregion
            #region 增加Person表记录
            var person = new NameValue<string, object>
            { 
                { "UserID", uid },
                {"TackPassword",md5.ComputeHash("123456", salt)}
            };
            base.Insert<Person>(person);
            #endregion
            #region 增加Account表记录
            NameValue<string, object> insertItem = new Models.NameValue<string, object>()
            {
                {"UserID",uid},
                {"Remark",""}
            };
            base.Insert<Account>(insertItem);
            #endregion
            #region 增加UserAddChildConfig表记录
            flag = type == UserType.Surrogate&&enableAddChildConfig;
            insertItem = new NameValue<string, object>()
            {
                {"UserID",uid},
                {"AllChildCount",flag?AllChildCount:0},
                {"FloorCount",string.IsNullOrEmpty(commands)?1:commands.Split('&').Length+1},
                {"Remark",""}
            };
            base.Insert<UserAddChildConfig>(insertItem);
            #endregion
            #region 修改UserAddChildConfig表记录
            if (!enableAddChildConfig&&commandID.HasValue)//如果启用就不修改，因为没启用就要使新增用户不占名额
            {
                var update = new NameValue<string, object>
                {
                    {"AllChildCount",new OpteratorValue(Opterator.Add,1)}
                };
                var where = new NameValue<string, object>
                {
                    {"NULL",new SqlExpression(" UserID={0} or (select commands from Users where ID={0}) like '%'+cast(UserID as varchar(max))+'%'",commandID.Value)}
                };
                base.Update<UserAddChildConfig>(update, where);
            }
            #endregion
            rs = base.ExecuteTransaction();
            if (Log.IsDebugEnabled)
                Log.Debug("Code.BLL.UserManage.AddUser user;" + u.ToString() + " rs:" + rs);
            if (rs > 0 && setWin)
            {
                var PM = new PlayTypeOptionManage();
                PM.SetUserOptionByMargin(commandID, uid.Value, null, null, null, null, true, manage);
            }
            return rs;
        }

        /// <summary>
        /// 修改登录密码
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="loginPwd"></param>
        /// <returns></returns>
        public int EditLoginPwd(Guid uid, string loginPwd)
        {
            if (string.IsNullOrEmpty(loginPwd))
                throw new ArgumentNullException("loginPwd");
            var user = base.Select(s => s.FirstOrDefault(p => p.ID == uid));
            if (user == null)
                throw new ArgumentNullException("uid", "没有找到当前用户");
            var newPwd = MD5.Create().ComputeHash(loginPwd, user.Salt);
            return base.Update(new NameValue<string, object> { { "Password", newPwd } }, new NameValue<string, object> { { "ID", uid } });
        }
        /// <summary>
        /// 修改提款密码
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="takePwd"></param>
        /// <returns></returns>
        public int EditTakePwd(Guid uid, string takePwd)
        {
            if (string.IsNullOrEmpty(takePwd))
                throw new ArgumentNullException("takePwd");
            var user = base.Select(s => s.FirstOrDefault(p => p.ID == uid));
            if (user == null)
                throw new ArgumentNullException("uid", "没有找到当前用户");
            var newPwd = MD5.Create().ComputeHash(takePwd, user.Salt);
            return base.Update<Person>(new NameValue<string, object> { { "TackPassword", newPwd } }, new NameValue<string, object> { { "UserID", uid } });
        }
        /// <summary>
        /// 获取从指定时间至今无账变的用户(但有可能有余额)
        /// </summary>
        /// <param name="stateTime">要搜索至今没有交易记录的起始日期</param>
        /// <param name="minMoney">用户金额不能过低的最小金额</param>
        /// <param name="uid">要从哪个用户的下级中获取,默认为没有这个限制</param>
        /// <returns></returns>
        public IEnumerable<User_Comm> GetNoAccountUsers(DateTime? stateTime,Guid? uid=null)
        {
            return GetNoAccountUsers(stateTime,false,null,uid);
        }
        /// <summary>
        ///获取从指定时间至今无账变无余额用户
        /// </summary>
        /// <param name="stateTime">要搜索至今没有交易记录的起始日期</param>
        /// <param name="minMoney">用户金额不能过低的最小金额</param>
        /// <param name="uid">要从哪个用户的下级中获取,默认为没有这个限制</param>
        /// <returns></returns>
        public IEnumerable<User_Comm> GetNoAccountUsers(DateTime? stateTime,double? minMoney,Guid? uid=null)
        {
            return GetNoAccountUsers(stateTime, true, minMoney, uid);
        }
        /// <summary>
        /// 获取无账变用户
        /// </summary>
        /// <param name="stateTime">要搜索至今没有交易记录的起始日期</param>
        /// <param name="comparMoney">是否要奖总金额作为条件筛选</param>
        /// <param name="minMoney">用户金额不能过低的最小金额</param>
        /// <param name="uid">要从哪个用户的下级中获取,默认为没有这个限制</param>
        /// <returns></returns>
        private IEnumerable<User_Comm> GetNoAccountUsers(DateTime? stateTime,bool comparMoney,double? minMoney=null,Guid? uid=null)
        { 
            if(stateTime==null)
                stateTime=DateTime.Now;
            if(minMoney==null)
                minMoney=0;
            var money=(decimal)minMoney.Value;
            var data = base.Select(s => s);
            if (uid.HasValue)
                data = data.Where(p => p.Commands.EndsWith(uid.Value.ToString()));
            if (comparMoney)
                //总金额小于最低金额
                data=data.Where(p=>p.Account.Balance + p.Account.FreezeMoney <= money);
            return data.Where(p =>
                    //还没停止的追号的发起人中不包括当前用户
                !p.ChaseTask.Select(p1 => p1.StopTime!=null&&p1.StopTime < DateTime.Now && p1.StopTime < stateTime.Value).Contains(false)
                    //当前期方案的发起人中不包括当前用户
                && !p.Scheme.Select(p1 => p1.AddTime < DateTime.Now && p1.AddTime < stateTime.Value).Contains(false)
                &&!Tables.UserAccountDetail.Where(p1=>p1.AddTime>=DateTime.Now.AddDays(-7)||p1.AddTime>=stateTime.Value).Select(p1=>p1.UserID).Contains(p.ID)
                ).Select(p => new User_Comm 
                {
                    Uid=p.ID,
                    CommandID=p.CommandID,
                    Commmands=p.Commands,
                    LoginName=p.LoginName,
                    UserTye=p.UserType,
                    RegistTime=p.RegistTime,
                    Money=(double)(p.Account.Balance+p.Account.FreezeMoney)
                });
        }
        public IEnumerable<User_Comm> GetCommand(Guid? uid)
        {
            return base.Select(s => s.Join(Tables.GetCommand(uid), p => p.ID, p => p.ID, (p1, p2) => new User_Comm 
            {
                Uid=p1.ID,
                CommandID=p1.CommandID,
                Commmands=p1.Commands,
                LoginName=p1.LoginName,
                RegistTime=p1.RegistTime,
                Money=(double)(p1.Account.FreezeMoney+p1.Account.Balance),
                UserTye=p1.UserType
            }));
        }

        /// <summary>
        /// 获取当前用户的所有下级信息
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="sub">是否包含所有子级</param>
        /// <param name="where">另类的查询字符串</param>
        /// <param name="paramList">查询字符串的参数</param>
        /// <returns></returns>
        public IEnumerable<AllChild_Mod> GetUserChild(Guid uid, bool sub, string where, params object[] paramList)
        {
            IQueryable<Users> subChilds = null;
            if (sub)
            {
                subChilds = base.Select(s => s.Where(p => p.Commands.Contains(uid.ToString())));
            }
            else
            {
                subChilds = base.Select(s => s.Where(p => p.CommandID == uid));
            }
            var data= subChilds.Select(p => new
                {
                    p.ID,
                    p.LoginName, 
                    p.RegistTime,
                    Balance = p.Account.Balance,
                    p.State,
                    p.UserType,
                    LastLoginTime = p.LoginLog.OrderByDescending(p1 => p1.LoginTime).Select(p1 => p1.LoginTime).FirstOrDefault()
                })
                .Where(string.IsNullOrEmpty(where)?" 1==1 ":where, paramList)
                .Select(p => new AllChild_Mod
                {
                    Uid = p.ID,
                    ChildName = p.LoginName,
                    Balance = (double)p.Balance,
                    RegistTime = p.RegistTime,
                    LastLoginTime = p.LastLoginTime ,
                    State=(UserState)p.State,
                    Type=p.UserType
                });
            return data;
        }

        /// <summary>
        /// 获取当前用户的所有下级信息
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="sub">是否包含所有子级</param>
        /// <param name="skip">分页时要跳过的条数</param>
        /// <param name="take">分页时要提取的条数</param>
        /// <param name="sumCount">分页前总条数</param>
        /// <param name="balanceASC">是否要对余额做排序，做哪种排序</param>
        /// <param name="regestTimeASC">是否要对注册时间做排序，做哪种排序</param>
        /// <param name="where">另类的查询字符串</param>
        /// <param name="paramList">查询字符串的参数</param>
        /// <returns></returns>
        public IEnumerable<AllChild_Mod> GetUserChild(Guid uid, bool sub, int skip, int take, out int sumCount, bool? balanceASC = false,  bool? regestTimeASC = null, string where = null, params object[] paramList)
        {
            IQueryable<Users> subChilds = null;
            sumCount = 0;
            if (sub)
            {
                subChilds = base.Select(s => s.Where(p => p.Commands.Contains(uid.ToString())));
            }
            else
            {
                subChilds = base.Select(s => s.Where(p => p.CommandID == uid));
            }
            var data = subChilds.Select(p => new
            {
                p.ID,
                p.LoginName,
                p.RegistTime,
                Balance = p.Account.Balance,
                p.State,
                p.UserType,
                LastLoginTime = p.LoginLog.OrderByDescending(p1 => p1.LoginTime).Select(p1 => p1.LoginTime).FirstOrDefault()
            })
                .Where(string.IsNullOrEmpty(where) ? " 1==1 " : where, paramList);
            sumCount = data.Count();

            if (balanceASC.HasValue)
            {
                if (balanceASC.Value)
                    data = data.OrderBy(p => p.Balance);
                else
                    data = data.OrderByDescending(p => p.Balance);
            }


            if (regestTimeASC.HasValue)
            {
                if (regestTimeASC.Value)
                    data = data.OrderBy(p => p.RegistTime);
                else
                    data = data.OrderByDescending(p => p.RegistTime);
            }

            var list = data.Skip(skip).Take(take).Select(p => new AllChild_Mod
            {
                Uid = p.ID,
                ChildName = p.LoginName,
                Balance = (double)p.Balance,
                RegistTime = p.RegistTime,
                LastLoginTime = p.LastLoginTime,
                State = (UserState)p.State,
                Type = p.UserType
            });
            return list.ToList();
        }


        /// <summary>
        /// 获取所有用户信息
        /// </summary>
        /// <param name="balanceASC">是否要对余额做排序，做哪种排序</param>
        /// <param name="regestTimeASC">是否要对注册时间做排序，做哪种排序</param>
        /// <param name="where">另类的查询字符串</param>
        /// <param name="paramList">查询字符串的参数</param>
        /// <returns></returns>
        public IEnumerable<AllChild_Mod> GetUserChild( bool? balanceASC = false, bool? regestTimeASC = null, string where=null, params object[] paramList)
        {
            var data = base.Select(s => s.Select(p => new
                {
                    p.ID,
                    p.LoginName,
                    p.RegistTime,
                    Balance = p.Account.Balance,
                    p.UserType,
                    LastLoginTime = p.LoginLog.OrderByDescending(p1 => p1.LoginTime).Select(p1 => p1.LoginTime)
                }).Where(string.IsNullOrEmpty(where) ? " 1==1 " : where, paramList));


            if (balanceASC.HasValue)
            {
                if (balanceASC.Value)
                    data = data.OrderBy(p => p.Balance);
                else
                    data = data.OrderByDescending(p => p.Balance);
            }
            else
                data = data.OrderByDescending(p => p.Balance);


            if (regestTimeASC.HasValue)
            {
                if (regestTimeASC.Value)
                    data = data.OrderBy(p => p.RegistTime);
                else
                    data = data.OrderByDescending(p => p.RegistTime);
            }

             var subChilds=data.Select(p => new AllChild_Mod
                {
                    Uid = p.ID,
                    ChildName = p.LoginName,
                    Balance = (double)p.Balance,
                    RegistTime = p.RegistTime,
                    LastLoginTime = p.LastLoginTime == null ? null : new DateTime?(p.LastLoginTime.FirstOrDefault()),
                    Type=p.UserType,
                    ChildsCount = Tables.GetChids(p.ID).Count()
                });
            return subChilds;
        }

        /// <summary>
        /// 获取所有用户信息
        /// </summary>
        /// <param name="skip">获取最后的结果时要跳过的条数</param>
        /// <param name="take">获取最后的结果时要获取的条数</param>
        /// <param name="count">返回符合条件的总条数</param>
        /// <param name="balanceASC">是否要对余额做排序，做哪种排序</param>
        /// <param name="regestTimeASC">是否要对注册时间做排序，做哪种排序</param>
        /// <param name="where">另类的查询字符串</param>
        /// <param name="paramList">查询字符串的参数</param>
        /// <returns></returns>
        public IEnumerable<AllChild_Mod> GetUserChild(int skip, int take, out int count, bool? balanceASC = false, bool? regestTimeASC = null, string where=null, params object[] paramList)
        {
            count = 0;
            var data = base.Select(s => s.Select(p => new
                {
                    p.ID,
                    p.LoginName,
                    p.RegistTime,
                    Balance = p.Account.Balance,
                    p.UserType,
                    LastLoginTime = p.LoginLog.OrderByDescending(p1 => p1.LoginTime).Select(p1 => p1.LoginTime)
                }).Where(string.IsNullOrEmpty(where) ? " 1==1 " : where, paramList));
            count = data.Count();


            if (balanceASC.HasValue)
            {
                if (balanceASC.Value)
                    data = data.OrderBy(p => p.Balance);
                else
                    data = data.OrderByDescending(p => p.Balance);
            }
            else
                data = data.OrderByDescending(p => p.Balance);


            if (regestTimeASC.HasValue)
            {
                if (regestTimeASC.Value)
                    data = data.OrderBy(p => p.RegistTime);
                else
                    data = data.OrderByDescending(p => p.RegistTime);
            }

             var subChilds=data.Skip(skip).Take(take).Select(p => new AllChild_Mod
                {
                    Uid = p.ID,
                    ChildName = p.LoginName,
                    Balance = (double)p.Balance,
                    RegistTime = p.RegistTime,
                    LastLoginTime = p.LastLoginTime == null ? null : new DateTime?(p.LastLoginTime.FirstOrDefault()),
                    Type=p.UserType,
                    ChildsCount = Tables.GetChids(p.ID).Count()
                });
            return subChilds;
        }

        /// <summary>
        /// 获取用户的上级(包括自己)
        /// </summary>
        /// <param name="uid">当前用户ID</param>
        public IEnumerable<AllParent_Mod> GetUserParent(Guid uid)
        {
            return base.Select<Users, IEnumerable<AllParent_Mod>>(s => s
                .Join(Tables.GetCommand(uid), p => p.ID, p => p.ID, (p1, p2) => 
                    new AllParent_Mod { CommandID = p1.CommandID, Uid = p1.ID, LoginName = p1.LoginName, Commands=p1.Commands,UserType=p1.UserType }));
        }

        /// <summary>
        /// 判断Email是否存在
        /// </summary>
        /// <param name="email">Email</param>
        public bool BoolEmail(string email)
        {
            return base.Select(s => s.Select(p => p.Person.Email).Contains(email));
        }

        /// <summary>
        /// 判断用户名是否存在
        /// </summary>
        /// <param name="email">Email</param>
        public bool BoolLoginName(string loginName)
        {
            return base.Select(s => s.Select(p => p.LoginName).Contains(loginName));
        }

        /// <summary>
        /// 删除指定用户，将指定用户的下级转移到指定的用户下，默认转移到要删除的用户的直接上级
        /// </summary>
        /// <param name="uid">要删除的用户</param>
        /// <param name="commandID">要转移下级到另一个用户的ID，默认转移到要删除的用户的直接上级</param>
        /// <returns></returns>
        public int DeleteUser(Guid uid,out string msg, Guid? childCommandID=null)
        {
            msg = string.Empty;
            var user = base.Select(s => s.FirstOrDefault(p => p.ID == uid));
            if (user == null)
            {
                msg = "当前用户未找到";
                return -1;
            }
            int? count = -1;
            if (user.UserType == (short)UserType.Surrogate)
            {
                count=UpdateUserType(uid, out msg, true, childCommandID);
                if (count < 0)
                {
                    if (Log.IsDebugEnabled)
                        Log.Debug(string.Format("在删除用户操作中转移用户下级发生错误。错误原因:{0},参数:{1},{2}",msg,uid,childCommandID.HasValue?childCommandID.Value.ToString():""));
                    if (Log.IsWarnEnabled)
                        Log.Warn(string.Format("在删除用户操作中转移用户下级发生错误。错误原因:{0}",msg));
                    return count.Value;
                }
            }
            base.Tables.DeleteUserByID(uid, ref count);
            if (count < 0&&user.UserType==(short)UserType.Surrogate)
            {
                msg = "删除用户失败，但用户的下级已成功转移。";
                if (Log.IsDebugEnabled)
                    Log.Debug(string.Format("删除用户操作时发生错误。参数:{0},{1}",uid,childCommandID.HasValue?childCommandID.Value.ToString():""));
                return count.Value;
            }
            else if (count < 0)
            {
                msg = "删除用户失败";
                if (Log.IsDebugEnabled)
                    Log.Debug(string.Format("删除用户操作时发生错误。参数:{0},{1}", uid, childCommandID.HasValue ? childCommandID.Value.ToString() : ""));
            }
            return count.HasValue?count.Value:-1;
        }

        /// <summary>
        /// 修改用户登录密码
        /// </summary>
        /// <param name="uid">用户编号</param>
        /// <param name="oldPwd">旧密码</param>
        /// <param name="newPwd">新密码</param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public int EditUserPassword(Guid uid,string oldPwd,string newPwd,out string msg)
        {
            msg = "";
            if (string.IsNullOrEmpty(oldPwd))
                throw new ArgumentNullException("oldPwd");
            if (string.IsNullOrEmpty(newPwd))
                throw new ArgumentNullException("newPwd");
            var user = base.Select(s => s.Where(p => p.ID == uid).Select(p => new {p.Salt,p.Password }).FirstOrDefault());
            if (user == null)
            {
                msg = "用户名不存在。";
                return -1;
            }
            MD5 md5 = MD5.Create();
            var flag = md5.ComputeHash(oldPwd, user.Salt).Equals(user.Password);
            if (!flag)
            {
                msg = "旧密码输入错误，请重新输入！";
                return -1;
            }
            NameValue<string, object> update = new NameValue<string, object>()
            {
                {"Password",md5.ComputeHash(newPwd,user.Salt)}
            };
            NameValue<string, object> where = new NameValue<string, object>()
            {
                {"ID",uid}
            };
            var count = base.Update(update, where);
            if (count > 0)
                msg = "密码修改成功！";
            else
                msg = "操作失败,请稍后再试！";
            return count;
        }

        /// <summary>
        /// 修改用户的提款密码
        /// </summary>
        /// <param name="uid">用户编号</param>
        /// <param name="oldPwd">旧密码</param>
        /// <param name="newPwd">新密码</param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public int EditUserTackPwd(Guid uid, string oldPwd, string newPwd, out string msg)
        {
            msg = "";
            if (string.IsNullOrEmpty(oldPwd))
                throw new ArgumentNullException("oldPwd");
            if (string.IsNullOrEmpty(newPwd))
                throw new ArgumentNullException("newPwd");
            var person = base.Select<Person, Person>(s => s.FirstOrDefault(p => p.UserID == uid));
            if (person == null)
            {
                msg = "用户资料不完整，请先完善资料。";
                return -1;
            }
            MD5 md5 = MD5.Create();
            var flag = md5.ComputeHash(oldPwd, person.Users.Salt).Equals(person.TackPassword);
            if (!flag)
            {
                msg = "旧密码输入错误，请重新输入！";
                return -1;
            }
            NameValue<string, object> update = new NameValue<string, object>()
            {
                {"TackPassword",md5.ComputeHash(newPwd,person.Users.Salt)}
            };
            NameValue<string, object> where = new NameValue<string, object>()
            {
                {"UserID",uid}
            };
            var count = base.Update<Person>(update, where);
            if (count > 0)
                msg = "密码修改成功！";
            else
                msg = "操作失败,请稍后再试！";
            return count;
        }


        /// <summary>
        /// 更新Person表
        /// </summary>
        /// <param name="update">要更新的属性,类的属性名要和表的列名一致</param>
        /// <param name="where">做为筛选的条件,类的属性名要和表的列名一致 无条件则为 null</param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>更新的行数</returns>
        public int UpdatePerson(object update, object where)
        {
            return base.Update<Person>(update, where);
        }

        /// <summary>
        /// 更新Users表,不能用户此方法更新用户类型
        /// </summary>
        /// <param name="update">要更新的属性,类的属性名要和表的列名一致</param>
        /// <param name="where">做为筛选的条件,类的属性名要和表的列名一致 无条件则为 null</param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>更新的行数</returns>
        public int UpdateUser(object update, object where)
        {
            return base.Update<Person>(update, where);
        }
        /// <summary>
        /// 更新用户类型
        /// (已启用事务)
        /// </summary>
        /// <param name="uid">要更新的用户的ID</param>
        /// <param name="msg">输出的消息</param>
        /// <param name="beginTran">是否需要开启事务</param>
        /// <param name="commandID">要转移下级到另一个用户的ID，默认转移到当前用户的直接上级</param>
        /// <returns></returns>
        public int UpdateUserType(Guid uid,out string msg,bool beginTran,Guid? commandID=null)
        {
            msg = "";
            var user = base.Select(s => s.FirstOrDefault(p => p.ID == uid));
            if (user == null)
            {
                msg = "不存在当前用户";
                return -1;
            }
            if (user.UserType == (short)UserType.Member)
            {
                if (beginTran)
                    base.BeginTransaction();
                base.Update(new { Type = (short)UserType.Surrogate }, new { ID = uid });
                if (beginTran)
                    return base.ExecuteTransaction();
                return -1;
            }
            else
            {
                var newCommands = "";
                var userCommands = string.IsNullOrEmpty(user.Commands) ? "" + user.ID : user.Commands + "&" + user.ID;
                if (commandID != null)
                {
                    var command = base.Select(s => s.FirstOrDefault(p => p.ID == commandID));
                    if (command == null)
                    {
                        msg = "未找到作为当前用户直属下级的上级的会员";
                        return -3;
                    }
                    if (command.UserType == (short)UserType.Member)
                    {
                        msg = "要作为当前用户直属下级的上级的会员不是代理";
                        return -4;
                    }
                    newCommands = command.Commands == "" ? "" + command.ID : command.Commands + "&" + command.ID;
                }
                else
                {
                    commandID = user.CommandID;
                    newCommands = user.Commands;
                }
                var list = base.Select(s => s.Where(p => p.CommandID == user.ID));
                var update = new NameValue<string, object>
                {
                    {"commands",new SqlExpression("Replace(commands,{0},{1})",userCommands,newCommands)}
                };
                var where = new NameValue<string, object>
                {
                    {"commands",new ComparValue(Comparison.Sql,new SqlExpression("like '%'+{0}+'%'",user.ID.ToString()))}
                };
                if (beginTran)
                    base.BeginTransaction();
                base.Update(update, where);
                update = new NameValue<string, object>
                {
                    {"commandID",commandID}
                };
                where = new NameValue<string, object>()
                {
                    {"commandID",user.ID}
                };
                base.Update(update, where);
                update = new NameValue<string, object>
                {
                    {"Type",(short)UserType.Member}
                };
                where = new NameValue<string, object>
                {
                    {"ID",user.ID}
                };
                base.Update(update, where);
                #region 修改配额
                update = new NameValue<string, object>
                {
                    {"AllChildCount",0},
                };
                where = new NameValue<string, object> { { "UserID", user.ID } };
                base.Update<UserAddChildConfig>(update, where);
                #endregion
                if (beginTran)
                    return base.ExecuteTransaction();
                return -1;
            }
        }

        public int UpdateLoginPwd(string loginName, string newPwd)
        {
            if (string.IsNullOrEmpty(loginName))
                return -1;
            var user = base.Select(s => s.Where(p => p.LoginName == loginName).FirstOrDefault());
            if (user == null)
                return -1;
            var loginPwd = MD5.Create().ComputeHash(newPwd, user.Salt);
            return base.Update(new NameValue<string, object> {{"Password",loginPwd} }, new NameValue<string,object> {{"ID",user.ID} });
        }

        /// <summary>
        /// 用户冻结金额(将用户金额放入冻结金额中,状态为:冻结)
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="currentState">用户的当前状态</param>
        /// <returns></returns>
        public int UserFreezeMoney(Guid uid,UserState currentState)
        {
            var account = base.Select<Account, Account>(s => s.Where(p => p.UserID == uid).FirstOrDefault());
            if (account == null)
                throw new AppException("没找到当前用户");
            var flag = base.Select<Option_User, bool>(s => s.Where(p => p.UserID == uid).Select(p => p.Key).Contains(Option_User_Key.UserFreezeMoney.ToString()));
            var UserOptionItem = new NameValue<string,object>
            {
                {"Key",Option_User_Key.UserFreezeMoney.ToString()},
                {"Value",account.Balance},
                {"UserID",uid}
            };
            var freezMoneyDetailItem = new  NameValue<string,object>
            {
                {"AddTime",DateTime.Now},
                {"FreezeCause",FreezeCause.Freeze_User},
                {"State",FreezeMoneyDetailState.Freeze},
                {"Money",account.Balance},
                {"UserID",uid}
            };
            var update_Account = new NameValue<string, object>
            {
                {"Balance",0},
                {"FreezeMoney",new OpteratorValue(Opterator.Add,account.Balance)}
            };
            var where_Account = new NameValue<string, object>
            {
                {"UserID",uid}
            };
            var update = new NameValue<string, object>
            {
                {"State",UserState.Freez}
            };
            var where = new NameValue<string, object>
            {
                {"Id",uid},
                {"State",currentState}//已确保当前用户不是别的锁定状态
            };
            base.BeginTransaction();
            if (!flag)
            {
                base.Insert<Option_User>(UserOptionItem);
            }
            base.Insert<FreezeMoneyDetail>(freezMoneyDetailItem);
            base.Update<Account>(update_Account, where_Account);
            base.Update(update, where);
            return base.ExecuteTransaction();
        }
        /// <summary>
        /// 用户解冻金额
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public int UserFreeMoney(Guid uid)
        {
            var option_User = base.Select<Option_User, Option_User>(s => s.Where(p => p.UserID == uid&&p.Key==Option_User_Key.UserFreezeMoney.ToString()).FirstOrDefault());
            if (option_User == null)
                throw new AppException("当前用户没有冻结金额");
            decimal money;
            if(!decimal.TryParse(option_User.Value,out money)||money<0)
                throw new AppException("用户冻结金额数据异常");
            var UserOptionItem = new NameValue<string, object>
            {
                {"Key",Option_User_Key.UserFreezeMoney.ToString()},
                {"Value",option_User.Value},
                {"UserID",uid}
            };
            var freezMoneyDetailItem = new NameValue<string, object>
            {
                {"AddTime",DateTime.Now},
                {"FreezeCause",FreezeCause.Free_User},
                {"State",FreezeMoneyDetailState.Free},
                {"Money",money},
                {"UserID",uid}
            };
            var update_Account = new NameValue<string, object>
            {
                {"Balance",new OpteratorValue(Opterator.Add,money)},
                {"FreezeMoney",new OpteratorValue(Opterator.Subtract,money)}
            };
            var where_Account = new NameValue<string, object>
            {
                {"UserID",uid}
            };
            var update = new NameValue<string, object>
            {
                {"State",UserState.Normal}
            };
            var where = new NameValue<string, object>
            {
                {"ID",uid},
                {"State",UserState.Freez}
            };
            base.BeginTransaction();
            base.Delete<Option_User>(UserOptionItem);
            base.Insert<FreezeMoneyDetail>(freezMoneyDetailItem);
            base.Update<Account>(update_Account, where_Account);
            base.Update(update, where);
            return base.ExecuteTransaction(4);
        }
        /// <summary>
        /// 判断登录密码是否正确
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="TakePwd"></param>
        /// <returns></returns>
        public bool BoolLoginPwd(Guid uid, string loginPwd)
        {
            var user = base.Select(s => s.Where(p => p.ID == uid).Select(p => new {p.Password,p.Salt }).FirstOrDefault());
            MD5 md5 = MD5.Create();
            return user != null && md5.ComputeHash(loginPwd, user.Salt).Equals(user.Password);
        }

        /// <summary>
        /// 判断提款密码是否正确
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="loginPwd"></param>
        /// <returns></returns>
        public bool BoolTakePwd(Guid uid, string TakePwd)
        {
            var user = base.Select(s => s.Where(p => p.ID == uid).Select(p => new {p.Person.TackPassword,p.Salt }).FirstOrDefault());
            
            MD5 md5 = MD5.Create();
            return user != null && md5.ComputeHash(TakePwd, user.Salt).Equals(user.TackPassword);
        }

        /// <summary>
        /// 用户账户统计报表
        /// </summary>
        /// <param name="serch">用户账户统计报表查询条件</param>
        /// <param name="userid">当前用户ID</param>
        /// <returns></returns>
        public IQueryable<UserAccountReport> GetUserAccountReport(UserAccountReportSerch serch, Guid? userid,Guid? currentuid=null)
        {
            var report = base.Select<UserAccountReport, IQueryable<UserAccountReport>>(s => s);
            if (serch.StartTime.HasValue)
                report = report.Where(p => p.Date >= serch.StartTime);
            if (serch.EndTime.HasValue)
                report = report.Where(p => p.Date <= serch.EndTime);

            if (!string.IsNullOrEmpty(serch.LoginName))
                report = report.Where(p => p.LoginName == serch.LoginName);
            if (userid.HasValue)
                report = report.Where(p => p.UserID == userid || p.Commands.Contains(userid.ToString()));
            if (currentuid.HasValue)
                report = report.Where(p => p.UserID == userid || p.Commands.Contains(currentuid.Value.ToString()));
            if (serch.UserType.HasValue)
                report = report.Where(p => p.UserType == (short)serch.UserType);

            return report;
        }
        /// <summary>
        /// 用户账户统计报表查询条件
        /// </summary>
        public class UserAccountReportSerch
        {
            public DateTime? StartTime { get; set; }
            public DateTime? EndTime { get; set; }
            public string LoginName { get; set; }
            public UserType? UserType { get; set; } 
        }

        /// <summary>
        /// 查询用户资金进出明细
        /// </summary>
        /// <param name="serch">查询的条件</param>
        /// <param name="userid">当前用户的ID</param>
        public IQueryable<UserAccountDetail> GetUserAccountDetail(UserAccountDetailSerch serch, Guid? userid,Guid? currentuid=null)
        {
            var detail = base.Select<UserAccountDetail, IQueryable<UserAccountDetail>>(s => s);

            if (serch.Type.HasValue)
                detail = detail.Where(p => p.Type == (int)serch.Type.Value);
            if (serch.StartTime.HasValue)
                detail = detail.Where(p => p.AddTime >= serch.StartTime.Value);
            if (serch.EndTime.HasValue)
                detail = detail.Where(p => p.AddTime < serch.EndTime.Value.Date.AddDays(1));
            if (serch.MinMoney.HasValue)
                detail = detail.Where(p => p.Money >= serch.MinMoney.Value);
            if (serch.MaxMoney.HasValue)
                detail = detail.Where(p => p.Money <= serch.MaxMoney.Value);
            if (!string.IsNullOrEmpty(serch.LoginName))
                detail = detail.Where(p => p.LoginName == serch.LoginName);
            if(userid.HasValue)
                detail = detail.Where(p => p.UserID == userid || p.Commands.Contains(userid.ToString()));
            if(currentuid.HasValue)
                detail = detail.Where(p => p.UserID == currentuid || p.Commands.Contains(currentuid.Value.ToString()));
            if (serch.UserType.HasValue)
                detail = detail.Where(p => p.UserType == (int)serch.UserType);

            return detail;
        }

        /// <summary>
        /// 给下级充值
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="userName"></param>
        /// <param name="childid"></param>
        /// <param name="childName"></param>
        /// <param name="money"></param>
        /// <returns></returns>
        public int MoveMoney(Guid uid,string userName, Guid childid,string childName, double money)
        {
            var myMoney = base.Select<Account, double>(s => (double)s.Where(p => p.UserID == uid).FirstOrDefault().Balance);
            if (myMoney < money)
                return -2;
            base.BeginTransaction();
            base.Update<Account>(new NameValue<string, object> { { "Balance", new OpteratorValue(Opterator.Subtract, money) } }, new NameValue<string, object> { { "UserID", uid } });
            base.Update<Account>(new NameValue<string, object> { { "Balance", new OpteratorValue(Opterator.Add, money) } }, new NameValue<string, object> { { "UserID", childid } });
            base.Insert<OtherMoneyDetail>(new NameValue<string, object> { 
                {"UserID",uid},
                {"Type",(short)OtherMoneyDetailType.AddSubMoney},
                {"Money",money},
                {"Memo",string.Format("{0}给下级({1})充值",userName,childName)}
            });
            base.Insert<AddMoneyDetail>(new NameValue<string,object>{
                {"UserID",childid},
                {"RefID",uid},
                {"Money",money},
                {"Type",(short)AddMoneyType.SurrogateAdd},
                {"Remark",string.Format("当前用户({0})的上级({1})充值",childName,userName)}
            });
            return base.ExecuteTransaction();
        }

        /// <summary>
        /// 用户资金进出明细查询条件
        /// </summary>
        public class UserAccountDetailSerch
        {
            public UserType? UserType { get; set; }
            public string LoginName{get;set;}
            public DateTime? StartTime{get;set;}
            public DateTime? EndTime{get;set;}
            public double? MinMoney{get;set;}
            public double? MaxMoney{get;set;}
            public UserAccountDetailType? Type { get; set; }
        }

    }
}
